package dao

import (
	"activity_srv/activity"
	"activity_srv/model"
	"bytes"
	"errors"
	"fmt"
	"github.com/fogleman/gg"
	"go.uber.org/zap"
	"image"
	"image/jpeg"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"smart-health-platforms/config"
	"smart-health-platforms/pkg"
	"time"
	model2 "user_srv/model"
)

// 设置分销规则
func SetDistribution(in *activity.SetDistributionRequest) (id int64, err error) {
	//接收参数
	distribution := model.DistributionSetting{
		FirstLevelRatio:  float64(in.FirstLevelRatio),
		SecondLevelRatio: float64(in.SecondLevelRatio),
		MinWithdraw:      float64(in.MinWithdraw),
		WithdrawFee:      float64(in.WithdrawFee),
	}
	//入库
	if err = distribution.Create(); err != nil {
		pkg.Error("设置分销规则失败", zap.Error(err))
		return 0, err
	}
	return int64(distribution.Id), err
}

// 设置分销用户
func SetDistributionUser(in *activity.SetDistributionUserRequest) (id int64, err error) {
	//判断用户是否存在
	user := model2.Users{
		Id: uint(in.UserId),
	}
	if err = user.GetUserInfoById(int(in.UserId)); err != nil {
		pkg.Error("查询用户失败", zap.Error(err))
		return 0, err
	}
	if user.Mobile == "" {
		pkg.Error("用户不存在")
		return 0, errors.New("用户不存在")
	}

	//接收参数
	distributionUser := model.DistributionUser{
		UserId:      uint32(in.UserId),
		TotalIncome: float64(in.TotalIncome),
		Available:   float64(in.Available),
		Frozen:      float64(in.Frozen),
		ParentId:    uint32(in.ParentId),
	}
	//查询用户是否已参与分销
	if err = distributionUser.GetUserId(int64(in.UserId)); err != nil {
		pkg.Error("查询用户是否已参与分销失败", zap.Error(err))
		return 0, err
	}
	if distributionUser.Id != 0 {
		pkg.Error("用户已参与分销")
		return 0, errors.New("用户已参与分销")
	}
	//入库
	if err = distributionUser.Create(); err != nil {
		pkg.Error("设置分销用户失败", zap.Error(err))
		return 0, err
	}
	return int64(distributionUser.Id), err
}

// 修改分销用户
func UpdateDistributionUser(in *activity.UpdateDistributionUserRequest) (id int64, err error) {
	//接收参数
	distributionUser := model.DistributionUser{
		UserId: uint32(in.UserId),
	}
	//查询用户是否已参与分销
	if err = distributionUser.GetUserId(int64(in.UserId)); err != nil {
		pkg.Error("查询用户是否已参与分销失败", zap.Error(err))
		return 0, err
	}
	if distributionUser.Id == 0 {
		pkg.Error("用户未参与分销")
		return 0, errors.New("用户未参与分销")
	}
	//修改分销父级id
	if err = distributionUser.Update(in.ParentId); err != nil {
		pkg.Error("修改分销父级id失败", zap.Error(err))
		return 0, err
	}
	return int64(distributionUser.Id), err
}

// 删除分销用户
func RemoveDistributionUser(in *activity.RemoveDistributionUserRequest) (id int64, err error) {
	//接收参数
	distributionUser := model.DistributionUser{
		UserId: uint32(in.UserId),
	}
	//查询用户是否已参与分销
	if err = distributionUser.GetUserId(int64(in.UserId)); err != nil {
		pkg.Error("查询用户是否已参与分销失败", zap.Error(err))
		return 0, err
	}
	if distributionUser.Id == 0 {
		pkg.Error("用户未参与分销")
		return 0, errors.New("用户未参与分销")
	}
	//删除分销用户
	if err = distributionUser.Remove(); err != nil {
		pkg.Error("删除分销用户失败", zap.Error(err))
		return 0, err
	}
	return int64(distributionUser.Id), err
}

// 获取分销设置详情
func GetDistribution(in *activity.GetDistributionRequest) (*model.DistributionSetting, error) {
	//接收参数
	distribution := model.DistributionSetting{
		Id: uint32(in.Distribution),
	}
	//查询分销设置详情
	if err := distribution.Detail(); err != nil {
		pkg.Error("查询分销设置详情失败", zap.Error(err))
		return nil, err
	}
	return &distribution, nil
}

// 获取用户下两级分销列表
func GetDistributionList(in *activity.GetDistributionListRequest) ([]*activity.DistributionUser, error) {
	//接收参数
	distributionUser := model.DistributionUser{
		UserId: uint32(in.UserId),
	}
	//查询用户是否已参与分销
	if err := distributionUser.GetUserId(int64(in.UserId)); err != nil {
		pkg.Error("查询用户是否已参与分销失败", zap.Error(err))
		return nil, err
	}
	if distributionUser.Id == 0 {
		pkg.Error("用户未参与分销")
		return nil, errors.New("用户未参与分销")
	}
	//查询用户下两级分销列表
	disUserList, err := distributionUser.GetTwoLevelUser()
	if err != nil {
		pkg.Error("查询用户下两级分销列表失败", zap.Error(err))
		return nil, err
	}

	//转换为pb模型
	var disUserListPb []*activity.DistributionUser
	for _, dis := range disUserList {
		list := activity.DistributionUser{
			Id:          int64(dis.Id),
			UserId:      int64(dis.UserId),
			NiceName:    dis.NickName,
			TotalIncome: float32(dis.TotalIncome),
			Available:   float32(dis.Available),
			Frozen:      float32(dis.Frozen),
			ParentId:    int64(dis.ParentId),
			CreatedAt:   dis.CreatedAt.Format("2006-01-02 15:04:05"),
		}
		disUserListPb = append(disUserListPb, &list)
	}

	return disUserListPb, nil
}

// 获取个人分销信息
func GetUserDistributionInfo(in *activity.GetUserDistributionInfoRequest) (*activity.GetUserDistributionInfoResponse, error) {
	// 参数校验
	if in.UserId == 0 {
		return nil, errors.New("用户ID不能为空")
	}
	//接收参数
	distributionUser := model.DistributionUser{UserId: uint32(in.UserId)}
	distributionCommission := model.DistributionCommission{UserId: uint32(in.UserId)}
	//查询用户是否已参与分销
	if err := distributionUser.GetUserId(in.UserId); err != nil {
		pkg.Error("查询用户是否已参与分销失败", zap.Error(err))
		return nil, err
	}
	log.Println(distributionUser.Id)
	if distributionUser.Id == 0 {
		pkg.Error("用户未参与分销")
		return nil, errors.New("用户未参与分销")
	}
	//查询用户信息
	if err := distributionUser.GetUserInfo(); err != nil {
		pkg.Error("查询用户信息失败", zap.Error(err))
		return nil, err
	}
	//根据用户id查询用户下两级分销流水
	commissionList, err := distributionCommission.GetUserDistributionCommissionList(uint32(in.UserId))
	if err != nil {
		pkg.Error("查询用户下两级分销流水失败", zap.Error(err))
		return nil, err
	}
	//转换为pb模型
	var commissionListPb []*activity.Commission
	for _, dis := range commissionList {
		list := activity.Commission{
			Id:          int64(dis.Id),
			UserId:      int64(dis.UserId),
			OrderSn:     dis.OrderSn,
			OrderAmount: float32(dis.OrderAmount),
			ToUserId:    int64(dis.ToUserId),
			Amount:      float32(dis.Amount),
			Level:       int64(dis.Level),
			Status:      int64(dis.Status),
			CreatedAt:   dis.CreatedAt.Format("2006-01-02 15:04:05"),
		}
		commissionListPb = append(commissionListPb, &list)
	}
	return &activity.GetUserDistributionInfoResponse{
		Id:          int64(distributionUser.Id),
		UserId:      int64(distributionUser.UserId),
		TotalIncome: float32(distributionUser.TotalIncome),
		Available:   float32(distributionUser.Available),
		Frozen:      float32(distributionUser.Frozen),
		Commission:  commissionListPb,
	}, nil
}

// 生成二级分销海报
func GeneratePoster(in *activity.GeneratePosterReq) (string, error) {
	//获取用户信息
	user := model.DistributionUser{
		UserId: uint32(in.UserId),
	}
	if err := user.GetUserId(int64(in.UserId)); err != nil {
		pkg.Error("查询用户信息失败", zap.Error(err))
		return "", err
	}
	if user.Id == 0 {
		pkg.Error("用户未参与分销")
		return "", errors.New("用户未参与分销")
	}

	//生成二维码，包含用户id,调用生成二维码的公共包
	qrCode, err := pkg.GenerateQRCode(in.UserId)
	if err != nil {
		pkg.Error("生成二维码失败", zap.Error(err))
		return "", err
	}

	// 3. 合成海报
	posterPath, err := CompositePoster(&user, qrCode)
	if err != nil {
		pkg.Error("合成海报失败", zap.Error(err))
		return "", err
	}

	// 4. 返回海报URL
	PosterUrl := config.POSTER_URL + filepath.Base(posterPath)
	pkg.Info("生成海报成功", zap.String("PosterUrl", PosterUrl))

	// 5. 保存海报URL到数据库
	poster := model.DistributionPosters{
		UserId:     uint32(in.UserId),
		PosterName: in.PosterName,
		PosterUrl:  PosterUrl,
	}
	if err = poster.Create(); err != nil {
		pkg.Error("保存海报URL到数据库失败", zap.Error(err))
		return "", err
	}
	pkg.Info("保存海报URL到数据库成功", zap.String("PosterUrl", PosterUrl))
	return PosterUrl, nil
}

// 合成海报
func CompositePoster(user *model.DistributionUser, qrCode image.Image) (string, error) {
	// 创建输出目录
	outputDir := config.OUTPUT_DIR
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		pkg.Error("创建输出目录失败", zap.Error(err))
		return "", fmt.Errorf("创建输出目录失败: %w", err)
	}
	// 检查目录是否真的创建成功
	if _, err := os.Stat(outputDir); os.IsNotExist(err) {
		pkg.Error("创建输出目录失败", zap.Error(err))
		return "", fmt.Errorf("目录不存在: %s", outputDir)
	}

	// 下载模板图片（从网络URL）
	templateUrl := config.TEMPLATEUrl
	templateImg, err := downloadImage(templateUrl)
	if err != nil {
		pkg.Error("下载模板图片失败", zap.Error(err))
		return "", fmt.Errorf("下载模板图片失败: %w", err)
	}

	// 创建绘图上下文
	bounds := templateImg.Bounds()
	dc := gg.NewContext(bounds.Dx(), bounds.Dy())
	dc.DrawImage(templateImg, 0, 0)

	// 绘制二维码（放在右下角）
	qrCodeWidth := 200
	qrCodeHeight := 200
	x := bounds.Dx() - qrCodeWidth - 50
	y := bounds.Dy() - qrCodeHeight - 50
	dc.DrawImage(qrCode, x, y)

	// 生成唯一文件名
	timestamp := time.Now().Unix()
	filename := fmt.Sprintf("poster_%d_%d.jpg", user.UserId, timestamp)
	outputPath := filepath.Join(outputDir, filename)

	// 保存图片
	outputFile, err := os.Create(outputPath)
	if err != nil {
		pkg.Error("创建输出文件失败", zap.Error(err))
		return "", fmt.Errorf("创建输出文件失败: %w", err)
	}
	defer outputFile.Close()

	// 保存生成的海报,以JPEG格式保存
	if err := jpeg.Encode(outputFile, dc.Image(), &jpeg.Options{Quality: 90}); err != nil {
		pkg.Error("保存JPEG失败", zap.Error(err))
		return "", fmt.Errorf("保存JPEG失败: %w", err)
	}

	// 以JPEG格式保存,返回海报url
	return outputPath, nil
}

// 下载图片(从给定的网络地址中进行，并将其解码为go语言中的image.Image对象)
func downloadImage(url string) (image.Image, error) {
	// 发送HTTP请求
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	// 检查HTTP响应状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP请求失败: %s", resp.Status)
	}
	// 读取图片数据
	imgData, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	// 解码图片
	img, _, err := image.Decode(bytes.NewReader(imgData))
	if err != nil {
		return nil, err
	}
	return img, nil
}

// 海报列表
func GetGeneratePoster(in *activity.GetGeneratePosterReq) ([]*activity.GeneratePosterInfo, error) {
	var poster model.DistributionPosters
	posterList, err := poster.List()
	if err != nil {
		pkg.Error("获取海报列表失败", zap.Error(err))
		return nil, err
	}

	var postersList []*activity.GeneratePosterInfo
	for _, posters := range posterList {
		list := activity.GeneratePosterInfo{
			Id:         int64(posters.Id),
			UserId:     int64(posters.UserId),
			PosterName: posters.PosterName,
			PosterUrl:  posters.PosterUrl,
			Status:     int64(posters.Status),
			CreatedAt:  posters.CreatedAt.Format("2006-01-02 15:04:05"),
		}
		postersList = append(postersList, &list)
	}
	pkg.Info("获取海报列表成功", zap.Any("postersList", postersList))
	return postersList, nil
}

// 提现
func GetUserWithdrawInfo(in *activity.GetUserWithdrawInfoRequest) (*model.DistributionWithdraw, error) {
	//获取提现比例
	var set model.DistributionSetting
	if err := set.Get(); err != nil {
		pkg.Error("获取提现比例失败", zap.Error(err))
		return nil, err
	}
	//添加提现记录
	withdraw := model.DistributionWithdraw{
		UserId:    uint32(in.UserId),                                                       //用户id
		Available: float64(in.WithdrawAmount),                                              //提现金额
		Withdraw:  float64(in.WithdrawAmount) * set.WithdrawFee,                            //手续费,提现金额*提现比例
		Obtain:    float64(in.WithdrawAmount) - float64(in.WithdrawAmount)*set.WithdrawFee, //获得金额,提现金额-手续费
	}
	//开启事务
	tx := config.DB.Begin()
	if err := withdraw.Create(tx); err != nil {
		tx.Rollback()
		pkg.Error("添加提现记录失败", zap.Error(err))
		return nil, err
	}
	//减少可用金额
	du := &model.DistributionUser{
		UserId:    uint32(in.UserId),
		Available: float64(in.WithdrawAmount), //可用金额
	}
	if err := du.ReduceAvailable(tx); err != nil {
		tx.Rollback()
		pkg.Error("减少可用金额失败", zap.Error(err))
		return nil, err
	}
	pkg.Info("减少可用金额成功")
	//提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		pkg.Error("提交事务失败", zap.Error(err))
		return nil, err
	}
	return &withdraw, nil
}

// 提现流水列表
func GetUserWithdrawList(in *activity.GetUserWithdrawListRequest) ([]*activity.WithdrawList, error) {
	var withdraw model.DistributionWithdraw
	withdraw.UserId = uint32(in.UserId)
	withdrawList, err := withdraw.List()
	if err != nil {
		pkg.Error("获取提现流水列表失败", zap.Error(err))
		return nil, err
	}
	//转换为pb模型
	var withdrawListPb []*activity.WithdrawList
	for _, withdraws := range withdrawList {
		list := activity.WithdrawList{
			Id:        int64(withdraws.Id),
			UserId:    int64(withdraws.UserId),
			Available: float32(withdraws.Available),
			Withdraw:  float32(withdraws.Withdraw),
			Obtain:    float32(withdraws.Obtain),
			CreatedAt: withdraws.CreatedAt.Format("2006-01-02 15:04:05"),
		}
		withdrawListPb = append(withdrawListPb, &list)
	}
	return withdrawListPb, nil
}

// 佣金排行榜
func GetUserWithdrawRank(in *activity.GetUserWithdrawRankRequest) ([]*activity.DistributionUser, error) {
	var du model.DistributionUser
	disUserList, err := du.SetRank()
	if err != nil {
		pkg.Error("获取佣金排行榜失败", zap.Error(err))
		return nil, err
	}
	//转换为pb模型
	var disUserListPb []*activity.DistributionUser
	for _, disUser := range disUserList {
		list := activity.DistributionUser{
			Id:          int64(disUser.Id),
			UserId:      int64(disUser.UserId),
			NiceName:    disUser.NickName,
			TotalIncome: float32(disUser.TotalIncome),
			Available:   float32(disUser.Available),
			Frozen:      float32(disUser.Frozen),
			ParentId:    int64(disUser.ParentId),
			CreatedAt:   disUser.CreatedAt.Format("2006-01-02 15:04:05"),
		}
		disUserListPb = append(disUserListPb, &list)
	}
	return disUserListPb, nil
}
